package drp.snowbell.part;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import drp.snowbell.annotation.APart;
import drp.snowbell.annotation.AProperty;
import drp.snowbell.entity.IEntity;
import drp.snowbell.entity.Property;
import drp.snowbell.storage.IStorage;
import drp.snowbell.storage.ITransaction;
import drp.snowbell.storage.StorageManager;
import drp.snowbell.util.StrHelper;


/**
 * 固定树技能,无限层级.如果树的结构不经常变动但是有很多层级请使用此技能.注意修改树结构,如果表的数据量大的话,会占用很大的资源
 * 
 * @author wuhj
 * 
 */
@APart(name = SolidTree.SKILL_NAME)
public class SolidTree extends PartBase {

	public final static String SKILL_NAME = "SolidTree";
	public final static String PROP_LEVEL = "Level";
	public final static String PROP_PARENT_VALUE = "ParentValue";
	public final static char LEVEL_SEPARATOR_CHAR = '/';

	/**
	 * 元素的层.layer+layerProperty的值是唯一的.layer为父元素的layer+父元素的layerProperty值.
	 * 根元素的layer为LEVEL_SEPARATOR_CHAR
	 */
	@AProperty
	private String layer;

	/**
	 * 父元素
	 */
	@AProperty
	private String parentValue;

	private Property layerProperty;
	private PartBlueprint sdna;
	private boolean isChangeParent = false;
	private String oldLayer;
	private IEntity parent;
	private ITransaction trans;

	public String getSkillName() {
		return SKILL_NAME;
	}

	public void setLayer(String layer) {
		this.layer = layer;
	}

	public String getLayer() {
		return layer;
	}

	public void setParentValue(String parentValue) {
		this.parentValue = parentValue;
	}

	public String getParentValue() {
		return parentValue;
	}

	public void onSaveStart() {
		if (isChangeParent) {
			IEntity entity = getTbean();
			String entityName = entity.getBeanName();
			if (!StrHelper.isNullOrEmpty(entity.getId())) {
				// 如果不是插数据, 需要自动更新所有子元素的层信息
				Map<Property, Object> map = new HashMap<Property, Object>();
				PartBlueprint sd = getSkillDna();
				// REPLACE LEVEL
				Property level = sd.getProperty(PROP_LEVEL);
				IExp replaceExp = ExpUtil.getReplaceFuncExp(level, oldLayer, generateLayerString(getParentValue()));
				map.put(level, replaceExp);
				if (map.size() > 0) {
					IStorage<IEntity> storage = StorageManager.getCurrentStorage(entityName);
					trans = storage.beginTransaction();
					storage.batchUpdate(map, null);
				}
			}
		}
	}

	public void onSaveEnd() {
		if (trans != null) {
			trans.commit();// 提交事务
			trans = null;
		}
	}

	public List<? extends IEntity> getChildren() {
		IEntity entity = getTbean();
		String entityName = entity.getBeanName();
		PartBlueprint sd = getSkillDna();
		Property prop = sd.getProperty("ParentValue");
		Object value = entity.getBasicValue(getLayerProp());
		IExp where = ExpUtil.getPvEqExp(prop, value);
		IStorage<IEntity> storage = StorageManager.getCurrentStorage(entityName);
		List<IEntity> list = storage.getList(where);
		return list;
	}

	public void setParent(IEntity parent) {
		if (parent == null) {
			this.parent = parent;
			if (!StrHelper.isNullOrEmpty(getParentValue())) {
				oldLayer = getParentValue();
				setParentValue(null);
				IEntity entity = getTbean();
				setLayer(StrHelper.safeToString(entity.getValue(getLayerProp())));
				isChangeParent = true;
			}
		} else {
			SolidTree parentTree = (SolidTree) parent.getPart(getSkillName());
			if (parentTree != null) {
				this.parent = parent;
				String unique = getParentValue();
				String parentValue = StrHelper.safeToString(parent.getValue(getLayerProp()));
				if (parentValue != null) {
					if (parentValue.equals(unique)) {
						// 如果相等直接返回
						return;
					}
				} else {
					return;
				}
				setLayer(generateLayerString(parentTree.getLayer()));
				setParentValue(parentValue);
				oldLayer = parentValue;
				isChangeParent = true;
			}
		}
	}

	public IEntity getParent() {
		if (parent == null) {
			String unique = getParentValue();
			if (unique != null) {
				IEntity entity = getTbean();
				if (entity != null) {
					String entityName = entity.getBeanName();
					if (!StrHelper.isNullOrEmpty(entityName)) {
						IStorage<IEntity> storage = StorageManager.getCurrentStorage(entityName);
						parent = storage.loadWithProp(getLayerProp(), unique);
					}
				}
			}
		}
		return parent;
	}

	/**
	 * 生成层字符串(例如:/level1/level2/level3/),注意开头和结尾都为LEVEL_SEPARATOR_CHAR
	 */
	private String generateLayerString(String parentLevel) {
		String ret = null;
		if (StrHelper.isNullOrEmpty(parentLevel)) {
			// 说明根目录
			ret = String.valueOf(LEVEL_SEPARATOR_CHAR);
		} else {
			ret = parentLevel + getParentValue() + LEVEL_SEPARATOR_CHAR;
		}
		return ret;
	}

	/**
	 * 从配置里获取作为layer的属性
	 * 
	 * @return
	 */
	private Property getLayerProp() {
		if (layerProperty == null) {
			IEntity entity = getTbean();
			String entityName = entity.getBeanName();
			Dna dna = Farm.getDna(entityName);

			String param = getParameter();
			if (StrHelper.isNullOrEmpty(param)) {
				layerProperty = dna.getIdProperty();
			} else {
				Property prop = dna.getProperty(param);
				if (prop != null) {
					if (prop.isRequired()) {
						layerProperty = prop;
					} else {
						throw new PropertyNeedRequiredException(prop);
					}
				}
			}
		}
		if (layerProperty == null) {
			throw new PropertyNotExistException(getParameter());
		}
		return layerProperty;
	}

	private PartBlueprint getSkillDna() {
		if (sdna == null) {
			IEntity entity = getTbean();
			if (entity != null) {
				String entityName = entity.getBeanName();
				sdna = PartManager.getSkillDna(entityName, getSkillName());
			}
		}
		return sdna;
	}

}
